package com.hyt.it.ogt.kq.common.gov.utils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;

import cn.hutool.core.util.ArrayUtil;

/**
 * <p>
 * 算法工具类
 * </p>
 *
 * @author Chengxh
 * @since 2021-08-14
 */
public class MathUtil {

    /**
     * 整数均分算法（递归）
     * @param number 整数（double类型，可以直接传int类型隐式转换为double）
     * @param partCount 粗略均分份数
     * @param partMaxSize 每份最大值
     * @param result 分配后的结果
     */
    public static void averageNumberByRecursive(double number, int partCount, int partMaxSize, List<Integer> result) {
        //清除上次递归数据
        result.clear();
        //将整数除以份数，并获取整数部分和小数部分
        DecimalFormat decimalFormat = new DecimalFormat("#.0");
        String averageStr = decimalFormat.format(number / partCount);
        String averageStrOneDecimal = averageStr.substring(0, averageStr.indexOf('.') + 2);
        int[] twoParts = splitDoubleByDot(Double.parseDouble(averageStrOneDecimal));
        int integerPart = twoParts[0];
        int decimalPart = twoParts[1];
        //小数部分为整数部分四舍五入
        if (decimalPart > 5) {
            integerPart++;
        }
        //分配所有份数到结果数组中
        for (int i = 0; i < partCount; i++) {
            result.add(integerPart);
        }
        //修改最后一份的值
        result.set(result.size() - 1, (int) (number - integerPart * (partCount - 1)));
        //检查结果中是否超过每份最大值
        boolean offset = false;
        for (Integer r : result) {
            if (r > partMaxSize) {
                offset = true;
                break;
            }
        }
        if (offset) {
            //超过每份最大值，均分份数加1，递归处理
            int newPartCount = partCount + 1;
            averageNumberByRecursive(number, newPartCount, partMaxSize, result);
        }
    }

//    /**
//     * 整数均分算法
//     * @param number 整数（double类型，可以直接传int类型隐式转换为double）
//     * @param partCount 均分份数
//     * @return 分配后的数组
//     */
//    public static int[] averageNumber(double number, int partCount) {
//        //将整数除以份数，并获取整数部分和小数部分
//        DecimalFormat decimalFormat = new DecimalFormat("#.0");
//        String averageStr = decimalFormat.format(number / partCount);
//        String averageStrOneDecimal = averageStr.substring(0, averageStr.indexOf('.') + 2);
//        int[] twoParts = splitDoubleByDot(Double.parseDouble(averageStrOneDecimal));
//        int integerPart = twoParts[0];
//        int decimalPart = twoParts[1];
//        //分配所有份数到结果数组中
//        int[] result = new int[partCount];
//        if ((int) number < partCount) {
//            //被均分的整数小于均分的份数，则将每个整数直接分配到结果数组中
//            for (int i = 0; i < partCount; i++) {
//                //第1次遍历，将结果数组中所有元素置为0
//                result[i] = 0;
//            }
//            for (int i = 0; i < (int) number; i++) {
//                //第2次遍历，将每个整数直接分配到结果数组中
//                result[i] = 1;
//            }
//        } else {
//            //被均分的整数大于或等于均分的份数
//            //小数部分为整数部分四舍五入
//            if (decimalPart > 5) {
//                integerPart++;
//            }
//            for (int i = 0; i < partCount - 1; i++) {
//                result[i] = integerPart;
//            }
//            //设置最后一份的值
//            result[partCount - 1] = (int) (number - integerPart * (partCount - 1));
//        }
//        return result;
//    }

    /**
     * 整数均分算法
     * @param number 整数
     * @param partCount 均分份数
     * @return 分配后的数组
     */
    public static int[] averageNumber(int number, int partCount) {
        //相除取整
        int integer = number / partCount;
        //取模
        int offset = number % partCount;
        //存在余数
        if (offset > 0) {
            //前半部分
            int[] pre = new int[partCount - offset];
            Arrays.fill(pre, integer);
            //后半部分
            int[] suf = new int[offset];
            Arrays.fill(suf, integer + 1);
            return ArrayUtil.addAll(pre, suf);
        }
        //不存在余数，完全平均分配
        int[] result = new int[partCount];
        Arrays.fill(result, integer);
        return result;
    }

    public static void main(String[] args) {
       int[] re = averageNumber(15, 10);
       System.out.println(Arrays.toString(re));
    }

    /**
     * 将小数分为整数部分和小数部分
     * @param num 小数
     * @return 整数部分与小数部分的数组
     */
    private static int[] splitDoubleByDot(double num){
        String str = Double.toString(num);
        String[] twoParts = str.split("\\.");
        int part1 = Integer.parseInt(twoParts[0]);
        int part2 = Integer.parseInt(twoParts[1]);
        return new int[]{part1, part2};
    }

    /**
     * 判断是否为整数
     * @param bd 数字
     * @return 是否为整数
     */
    public static boolean isIntegerValue(BigDecimal bd) {
        return bd.signum() == 0 || bd.scale() <= 0 || bd.stripTrailingZeros().scale() <= 0;
    }

    /**
     * 判断是否为正整数
     * @param bd 数字
     * @return 是否为正整数
     */
    public static boolean isPositiveInteger(BigDecimal bd) {
        //判断是否为整数
        if (MathUtil.isIntegerValue(bd)) {
            //是整数且为正数
            return bd.compareTo(BigDecimal.ZERO) > 0;
        }
        //不是整数
        return false;
    }

    /**
     * 判断是否为非负整数
     * @param bd 数字
     * @return 是否为非负整数
     */
    public static boolean isNonNegativeInteger(BigDecimal bd) {
        //判断是否为整数
        if (MathUtil.isIntegerValue(bd)) {
            //是整数，且为非负整数
            return bd.compareTo(BigDecimal.ZERO) >= 0;
        }
        //不是整数
        return false;
    }

}
